#ifndef prs_DataTest_H
#define prs_DataTest_H

#include "prs_Data.h"
#include "prs_DataTree.h"
#include "prs_DataFolders.h"
#include "prs_DataRegTables.h"

namespace prs {

///////////////////////////////////////////////////////////////////////////////

struct TDataTest
{
///////////////////////////////////////////////////////////////////////////////

  struct TDataVisitor : public svl::IVisitor<TDataTables>
                      , public svl::IVisitor<TDataTable>
                      , public svl::IVisitor<TDataFieldString>
                      , public svl::IVisitor<TDataTableRecord>
                      , public svl::IVisitor<TDataValueString>
  {
    int Value;
    //
    TDataVisitor(int V)           { Value = V;}
    TDataVisitor(TDataVisitor &V) { Value = V.Value;}
    //
    void Visit(TDataTables &Node) {
      TDataVisitor DV(456); 
      Node.AcceptChildren(DV);
    }
    //
    void Visit(TDataTable &Node) {
      Node.AcceptChildren(*this);
    }
    //
    void Visit(TDataFieldString &Node) {
      Node.AcceptChildren(*this);
    }


    //
    void Visit(TDataTableRecord &Node) {
      //Node.AcceptChildren(*this);
    }
    //
    void Visit(TDataValueString &Node) {
      Node.AcceptChildren(*this);
    }
  };

///////////////////////////////////////////////////////////////////////////////

  struct TFieldsVisitor : public svl::IVisitor<TDataTables>
                        , public svl::IVisitor<TDataTable>
                        , public svl::IVisitor<TDataFieldString>
                        , public svl::IVisitor<TDataFieldInteger>
                        , public svl::IVisitor<TDataFieldDouble>
                        , public svl::IVisitor<TDataFieldDateTime>
                        , public svl::IVisitor<TDataFieldRefR>
  {
    int Level;
    svl::TString SInfo;
    //
    TFieldsVisitor(int Level = 0) { 
      this->Level = Level;
      sOffs.FillToLen(Level*2,' ');
    }
    //
    void Visit(TDataTables &Node) {
      SInfo << sOffs << "Tables";
      FF(Node);
    }
    //
    void Visit(TDataTable &Node) {
      SInfo << sOffs << Node.TableId.GetValue();
      FF(Node);
    }
    //
    void Visit(TDataFieldString &Node) {
      SInfo << sOffs << Node.FieldId.GetValue() << "[s]";
      FF(Node);
    }
    //
    void Visit(TDataFieldInteger &Node) {
      SInfo << sOffs << Node.FieldId.GetValue() << "[i]";
      FF(Node);
    }
    //
    void Visit(TDataFieldDouble &Node) {
      SInfo << sOffs << Node.FieldId.GetValue() << "[d]";
      FF(Node);
    }
    //
    void Visit(TDataFieldDateTime &Node) {
      SInfo << sOffs << Node.FieldId.GetValue() << "[dt]";
      FF(Node);
    }
    //
    void Visit(TDataFieldRefR &Node) {
      SInfo << sOffs << Node.FieldId.GetValue() << "[r]";
      FF(Node);
    }

  private:  
    void FF(TAttrNode &Node) {
      TFieldsVisitor V(Level+1); 
      Node.AcceptChildren(V);
      SInfo << "\r\n" << V.SInfo;
    }
    svl::TString sOffs;
  };

///////////////////////////////////////////////////////////////////////////////

  struct TValuesVisitor : public svl::IVisitor<TDataTables>
                        , public svl::IVisitor<TDataTable>
                        , public svl::IVisitor<TDataTableRecord>
                        , public svl::IVisitor<TDataValueString>
                        , public svl::IVisitor<TDataValueInteger>
                        , public svl::IVisitor<TDataValueDouble>
                        , public svl::IVisitor<TDataValueDateTime>
                        , public svl::IVisitor<TDataValueRefR>
  {
    int Level;
    svl::TString SInfo;
    //
    TValuesVisitor(int Level = 0) { 
      this->Level = Level;
      sOffs.FillToLen(Level*2,' ');
    }
    //
    void Visit(TDataTables &Node) {
      SInfo << sOffs << "Tables";
      FF(Node);
    }
    //
    void Visit(TDataTable &Node) {
      SInfo << sOffs << Node.TableId.GetValue();
      FF(Node);
    }
    //
    void Visit(TDataTableRecord &Node) {
      SInfo << sOffs << "RecordId=" << Node.RecordId.GetValue();
      FF(Node);
    }
    //
    void Visit(TDataValueString &Node) {
      //SInfo << sOffs << Node.GetField()->FieldId.GetValue() << "[s] \"";// << Node.GetValue() << "\"";
      FF(Node);
    }
    //
    void Visit(TDataValueInteger &Node) {
      //SInfo << sOffs << Node.GetField()->FieldId.GetValue() << "[i]";
      FF(Node);
    }
    //
    void Visit(TDataValueDouble &Node) {
      //SInfo << sOffs << Node.GetField()->FieldId.GetValue() << "[d]";
      FF(Node);
    }
    //
    void Visit(TDataValueDateTime &Node) {
      //SInfo << sOffs << Node.GetField()->FieldId.GetValue() << "[dt]";
      FF(Node);
    }
    //
    void Visit(TDataValueRefR &Node) {
      //SInfo << sOffs << Node.GetField()->FieldId.GetValue() << "[r]";
      FF(Node);
    }

  private:  
    void FF(TAttrNode &Node) {
      TValuesVisitor V(Level+1); 
      Node.AcceptChildren(V);
      SInfo << "\r\n" << V.SInfo;
    }
    svl::TString sOffs;
  };

  //
  static void Test();
};

///////////////////////////////////////////////////////////////////////////////
}

#endif
